package com.jc.platform.contractzwl.service.base.impl;

import com.jc.platform.contractzwl.mapper.IPartherMapper;
import com.jc.platform.contractzwl.mapper.IRPartnerSalesContractMapper;
import com.jc.platform.contractzwl.mapper.ISalesContractMapper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;




import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jc.platform.common.annotation.DataIsolation;
import com.jc.platform.common.constants.GlobalConstant;
import com.jc.platform.common.constants.StringPool;
import com.jc.platform.common.model.UserInfo;
import com.jc.platform.common.model.QueryParam;
import com.jc.platform.common.result.PageInfo;
import com.jc.platform.common.result.ResultCodeEnum;
import com.jc.platform.common.result.ResultModel;
import com.jc.platform.common.search.SqlUtils;
import com.jc.platform.common.utils.BeanUtil;
import com.jc.platform.common.utils.RequestUtil;
import com.jc.platform.contractzwl.vo.SalesContractVO;
import com.jc.platform.contractzwl.entity.SalesContractEntity;
import com.jc.platform.contractzwl.mapper.ISalesContractMapper;
import com.jc.platform.contractzwl.service.base.impl.BaseServiceImpl;
import com.jc.platform.contractzwl.service.base.IBaseSalesContractService;
import com.jc.platform.mybatis.utils.CollectCovertUtil;
import com.jc.platform.mybatis.utils.ConditionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import com.jc.platform.contractzwl.vo.SalesContractStageVO;
import com.jc.platform.contractzwl.service.ISalesContractStageService;

import com.jc.platform.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.jc.platform.common.utils.CollectionUtil;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import com.jc.platform.contractzwl.mapper.IRPartnerSalesContractMapper;
import com.jc.platform.contractzwl.entity.RPartnerSalesContractEntity;

/**
 * ClassName AbstractSalesContractServiceImpl.java
 * Description 销售合同
 *
 * @author zwl
 * @version 9.0
 * @date 2021/08/07
 */
@Slf4j
public abstract class AbstractSalesContractServiceImpl extends BaseServiceImpl<SalesContractVO> implements IBaseSalesContractService
{
	private static final String KEY_PREFIX = "db_platformContractZwl:t_salesContract";

    @Autowired
    private RedisUtils<String, SalesContractVO> redisUtils;
    @Autowired
    private ISalesContractStageService salesContractStageService;
    @Autowired
    private IPartherMapper partherMapper;
    @Autowired
    private IRPartnerSalesContractMapper rPartnerSalesContractMapper;
    @Autowired
    private ISalesContractMapper salesContractMapper;



	@Override
	public ResultModel<SalesContractVO> insert(SalesContractVO salesContractVO)
	{
		SalesContractEntity entity = new SalesContractEntity();
		entity.copyFormVO(salesContractVO);
		salesContractMapper.insert(entity);
        List<SalesContractStageVO> salesContractStageList = salesContractVO.getSalesContractStageList();
        if(CollectionUtil.isNotEmpty(salesContractStageList)){
            salesContractStageList.forEach(item->{
                item.setSalesContractId(entity.getId());
                salesContractStageService.insert(item);
            });
        }
        List <Long> salesContractList = salesContractVO.getPartherList();
        if(CollectionUtil.isNotEmpty(salesContractList)){
            salesContractList.forEach(mtmId -> {
                RPartnerSalesContractEntity mtmEntity = new RPartnerSalesContractEntity();
                mtmEntity.setContractId(entity.getId());
                mtmEntity.setPartherId(mtmId);
                rPartnerSalesContractMapper.insert(mtmEntity);
            });
        }

		salesContractVO.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
		return ResultModel.success(salesContractVO);
	}

	@Override
	public ResultModel<SalesContractVO> update(SalesContractVO salesContract)
	{
		SalesContractEntity entity = new SalesContractEntity();
		entity.copyFormVO(salesContract);
		salesContractMapper.updateById(entity);
    //删除前台选中删除的集合数据
		List<Long> delSalesContractStageList = salesContract.getDelSalesContractStageList();
        salesContractStageService.deleteBatch(delSalesContractStageList);
        List<SalesContractStageVO> salesContractStageList = salesContract.getSalesContractStageList();
        if(CollectionUtil.isNotEmpty(salesContractStageList)){
            salesContractStageList.forEach(item->{
              if(item.getId()==null){
                    item.setSalesContractId(salesContract.getId());
                    salesContractStageService.insert(item);
                }else{
                    salesContractStageService.update(item);
                }
            });
        }

        rPartnerSalesContractMapper.deleteByContractId(salesContract.getId());
        List <Long> salesContractList = salesContract.getPartherList();
        if(CollectionUtil.isNotEmpty(salesContractList)){
            salesContractList.forEach(mtmId -> {
                RPartnerSalesContractEntity mtmEntity = new RPartnerSalesContractEntity();
                mtmEntity.setContractId(salesContract.getId());
                mtmEntity.setPartherId(mtmId);
                rPartnerSalesContractMapper.insert(mtmEntity);
            });
        }


		salesContract.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
        delFromRedisAsync(entity.getId());
		entity = salesContractMapper.selectById(entity.getId());
		return ResultModel.success(entity.copyToVO());
	}

    @Override
	public ResultModel<Boolean> delete(Long id)
	{
        if (!delCheck(id)) {
            return ResultModel.failed(ResultCodeEnum.REQUEST_PARAMS_ERROR.code(), "该条数据被其他数据关联");
        }
        
         int count = salesContractMapper.deleteById(id);

        rPartnerSalesContractMapper.deleteByContractId(id);
		if (count > 0)
		{
			delRedisKeyBatch(KEY_PREFIX);
            delFromRedisAsync(id);
			return ResultModel.success(true);
		}
		else
		{
			return ResultModel.success(false);
		}
	}

    @Override
	public ResultModel<Boolean> deleteBatch(List<Long> ids)
	{
        ids.forEach(id -> {
                if (!delCheck(id)) {
                    return;
                }
            salesContractMapper.deleteById(id);
        });

        delRedisKeyBatch(KEY_PREFIX);
        return ResultModel.success(true);
	}

    private boolean delCheck(Long id){
        QueryParam queryParam = new QueryParam();
        queryParam.setSortBy("id");
        String q;
        q = "sales_contract_id=" + id;
        queryParam.setQ(q);
        if (salesContractStageService.count(queryParam).getData() != 0) { 
            return false;
        } 
        return true;
    }



	@Override
	public Boolean checkNotExists(Long id, String property, String value)
	{
        QueryWrapper<SalesContractEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(BeanUtil.newInstance(SalesContractEntity.class));
        queryWrapper.eq(SqlUtils.getColumnByProperty(property), value);

        if(id!=null && id>0){
            queryWrapper.ne(StringPool.ID, id);
        }


        return salesContractMapper.selectCount(queryWrapper) <= 0;
	}

	@Override
	public ResultModel<SalesContractVO> get(Long id)
	{
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, id);
        SalesContractVO salesContractVO = getRedis(redisKey);
        if (salesContractVO == null)
        {
            SalesContractEntity entity = salesContractMapper.selectById(id);
            if (entity == null){
                return ResultModel.failed();
            }
            salesContractVO = entity.copyToVO();

            salesContractVO.setPartherPOList(CollectCovertUtil.listVO(partherMapper.findBySalesContract(id)));

            setRedis(redisKey, salesContractVO);
        }
        return ResultModel.success(salesContractVO);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<List<SalesContractVO>> find(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:find." + queryParam.toString());
        List<SalesContractVO> list = getRedisForList(redisKey);
            if (list == null || list.isEmpty())
            {
                QueryWrapper<SalesContractEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, SalesContractEntity.class);
                List<SalesContractEntity> entities = salesContractMapper.selectList(queryWrapper);
                list = CollectCovertUtil.listVO(entities);

                if (list != null && !list.isEmpty())
                {
                    if(CollectionUtil.isNotEmpty(list)){
                        list.stream().map(item -> {
                            item.setPartherList(rPartnerSalesContractMapper.findPartherIdByContractId(item.getId()));
                            return item;
                        })
                        .collect(Collectors.toList());
                    }
                    setRedis(redisKey,list);
                }
            }
        return ResultModel.success(list);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<PageInfo<SalesContractVO>> finds(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());

        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:finds." + queryParam.toString());
        PageInfo<SalesContractVO> page = getRedisForPage(redisKey);
        if (page == null)
        {
            QueryWrapper<SalesContractEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, SalesContractEntity.class);
            IPage<SalesContractEntity> entityPage = salesContractMapper.selectPage(ConditionUtil.getPage(queryParam), queryWrapper);
            page = CollectCovertUtil.pageVO(entityPage);


            if(CollectionUtil.isNotEmpty(page.getList())){
                page.getList().stream().map(item -> {
                    item.setPartherList(rPartnerSalesContractMapper.findPartherIdByContractId(item.getId()));
                    return item;
                })
                .collect(Collectors.toList());
            }
            setRedis(redisKey,page);
        }
        return ResultModel.success(page);

	}

    @Override
	public ResultModel<Integer> count(QueryParam queryParam)
	{
        QueryWrapper<SalesContractEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, SalesContractEntity.class);
        Integer count = salesContractMapper.selectCount(queryWrapper);
		return ResultModel.success(count);
	}



	@Override
	public ResultModel<List<SalesContractVO>> importData(List<SalesContractVO> salesContractList) {
		List<SalesContractEntity> saves = new ArrayList<>();
		List<SalesContractVO> returnList = new ArrayList<>();
		for (SalesContractVO salesContract : salesContractList) {
			SalesContractEntity entity = new SalesContractEntity();
			entity.copyFormVO(salesContract);
			saves.add(entity);
		}
		saves.forEach(entity -> {
			salesContractMapper.insert(entity);
			SalesContractVO salesContract = entity.copyToVO();
			returnList.add(salesContract);
		});
		return ResultModel.success(salesContractList);
	}
    /**
     * 执行【合作单位】添加
     *
     * @param id
     * @param partherId
     * @return
     */
    private int doAddParther(Long id, Long... partherId) {
        int count = 0;
        for (Long _id : partherId) {
            if(partherMapper.selectById(_id) != null){
                count += salesContractMapper.addParther(id, _id);
            }
        }
        return count;
    }

    /**
     * 设置【合作单位】
     *
     * @param id
     * @param partherId
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public int setParther(Long id, Long[] partherId) {
        salesContractMapper.removeAllParther(id);
        delFromRedisAsync(id);
        if(ArrayUtils.isEmpty(partherId)){
            return 0;
        }
        return doAddParther(id, partherId);
    }





    private void delFromRedisAsync(Object id)
	{
		CompletableFuture.runAsync(() -> {
			try
			{
				TimeUnit.SECONDS.sleep(1);
				redisUtils.del(RedisUtils.getRedisKey(KEY_PREFIX, id));
			}
			catch (InterruptedException e)
			{
				log.error("缓存删除线程错误", e);
				Thread.currentThread()
					  .interrupt();
			}
		});
	}

	private void delColRedis()
	{
		String keyPattern = RedisUtils.getRedisKey(KEY_PREFIX, "collection:*");
		Set<String> keys = redisUtils.keys(keyPattern);
		if (keys != null)
		{
			String[] keyArray = keys.toArray(new String[] {});
			redisUtils.del(keyArray);
		}
	}
}

